﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Krile.Kernel.Data;
using System.Text.RegularExpressions;

namespace Krile.Common
{
    public abstract class DefaultSearchDataBase : SearchData
    {
        public bool IsSearchDataMatched(string haystack)
        {
            if (haystack == null || Arguments.Length == 0) return false;
            switch (this.SearchType)
            {
                case SearchTypes.Equals:
                    return string.Compare(haystack, Arguments, IgnoreCase) == 0;
                case SearchTypes.StartsWith:
                    return haystack.StartsWith(Arguments,
                        IgnoreCase ? StringComparison.CurrentCultureIgnoreCase : StringComparison.CurrentCulture);
                case SearchTypes.EndsWith:
                    return haystack.EndsWith(Arguments,
                        IgnoreCase ? StringComparison.CurrentCultureIgnoreCase : StringComparison.CurrentCulture);
                case SearchTypes.Regex:
                    return Regex.Match(haystack, Arguments).Success;
                case SearchTypes.Contains:
                default:
                    return haystack.Contains(Arguments);
            }
        }

        public enum SearchTypes
        {
            Contains = 0,
            StartsWith,
            EndsWith,
            Equals,
            Regex
        };

        public sealed override Krile.Kernel.Control.SDataArgSetUI GetArgSetUI()
        {
            return new DSDataArgSetUI(this);
        }

        public string Arguments { get; set; }

        public bool IgnoreCase { get; set; }

        public SearchTypes SearchType { get; set; }

        public string GetCurrentSearchTypeName()
        {
            switch (SearchType)
            {
                case SearchTypes.Contains:
                    return Lang.DSData.SType_Partial;
                case SearchTypes.StartsWith:
                    return Lang.DSData.SType_Prefix;
                case SearchTypes.EndsWith:
                    return Lang.DSData.SType_Backward;
                case SearchTypes.Equals:
                    return Lang.DSData.SType_Perfect;
                case SearchTypes.Regex:
                    return Lang.DSData.SType_Regex;
                default:
                    return "Invalid";
            }
        }

        public sealed override void ReadXml(System.Xml.XmlReader reader)
        {
            int nsResult;
            if (int.TryParse(reader.GetAttribute("Type"), out nsResult))
                SearchType = (SearchTypes)nsResult;
            bool icResult;
            if (bool.TryParse(reader.GetAttribute("IgnoreCase"), out icResult))
                IgnoreCase = icResult;
            reader.ReadStartElement();
            Arguments = reader.ReadElementString("Argument");
            base.ReadXml(reader);
        }

        public sealed override void WriteXml(System.Xml.XmlWriter writer)
        {
            writer.WriteAttributeString("Type", ((int)SearchType).ToString());
            writer.WriteAttributeString("IgnoreCase", IgnoreCase.ToString());
            writer.WriteElementString("Argument", Arguments);
            base.WriteXml(writer);
        }

        public virtual object Clone(DefaultSearchDataBase instance)
        {
            instance.Arguments = this.Arguments;
            instance.Exclude = this.Exclude;
            instance.SearchType = this.SearchType;
            return instance;
        }

        public override string[] Methods
        {
            get { return new[] { "Equals", "StartsWith", "EndsWith", "Contains", "Regex" }; }
        }

        public override string GetCurrentMethod()
        {
            return this.SearchType.ToString();
        }

        protected override string WriteArguments()
        {
            if (IgnoreCase)
                return "\"" + this.Arguments + "\", true";
            else
                return "\"" + this.Arguments + "\"";
        }

        public override void AcceptArgument(string method, object[] arguments)
        {
            if (CheckTypeof(arguments, typeof(string)))
            {
                this.Arguments = arguments[0] as string;
                this.IgnoreCase = true;
            }
            else if (CheckTypeof(arguments, typeof(string), typeof(bool)))
            {
                this.Arguments = arguments[0] as string;
                this.IgnoreCase = (bool)arguments[1];
            }
            else
            {
                ThrowOverloadTypeError(new[] { typeof(string) }, new[] { typeof(string), typeof(bool) });
            }
        }
    }
}
